{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# TF Eager\n",
    "[ref](https://blog.csdn.net/wizardforcel/article/details/81211571)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "tf.logging.set_verbosity(tf.logging.ERROR)\n",
    "if tf.version.VERSION < '2.0.0':\n",
    "    import tensorflow.contrib.eager as tfe\n",
    "    tfe.enable_eager_execution()\n",
    "# eager is enabled default in tf 2.0\n",
    "#import tensorflow.compat.v1 as tf1\n",
    "#tf1.disable_eager_execution()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## create a model using keras API"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from tensorflow.keras import Model\n",
    "from tensorflow.layers import Dense\n",
    "\n",
    "class LR(Model):\n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "        self.hidden = Dense(10, activation=tf.nn.relu)\n",
    "        self.output_layer = Dense(2, activation=None)\n",
    "    def call(self, x):\n",
    "        x = self.hidden(x)\n",
    "        x = self.output_layer(x)\n",
    "        return x\n",
    "    def loss(self, inputs, target):\n",
    "        logits = self.call(inputs)\n",
    "        loss = tf.losses.sparse_softmax_cross_entropy(labels=target, logits=logits)\n",
    "        return loss"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## dummy data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.datasets import make_moons\n",
    "x, y = make_moons(n_samples=100, noise=0.1, random_state=2018)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "plt.scatter(x[:,0], x[:,1], c=y, cmap=plt.cm.autumn)\n",
    "plt.xlabel('First feature')\n",
    "plt.ylabel('Second feature')\n",
    "plt.title('Toy classification problem')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## train "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 0 Loss 0.6686\n",
      "Epoch 1 Loss 0.5993\n",
      "Epoch 2 Loss 0.5485\n",
      "Epoch 3 Loss 0.5085\n",
      "Epoch 4 Loss 0.4761\n",
      "Epoch 5 Loss 0.4500\n",
      "Epoch 6 Loss 0.4297\n",
      "Epoch 7 Loss 0.4136\n",
      "Epoch 8 Loss 0.4001\n",
      "Epoch 9 Loss 0.3886\n"
     ]
    }
   ],
   "source": [
    "num_epochs = 10\n",
    "inputs = tf.constant(x)\n",
    "target = tf.constant(y)\n",
    "\n",
    "model = LR()\n",
    "optimizer = tf.train.GradientDescentOptimizer(5e-1)\n",
    "for epoch in range(num_epochs):\n",
    "    with tfe.GradientTape() as tape:\n",
    "        loss = model.loss(inputs, target)\n",
    "        grads = tape.gradient(loss, model.variables)\n",
    "    optimizer.apply_gradients(zip(grads, model.variables))\n",
    "    print('Epoch {} Loss {:.4f}'.format(epoch, loss.numpy()))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
